/* 
 * Copyright (C) 2012 UTSChedule
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package utsc.apps.utschedule.ui.activities.adapters;

import java.util.ArrayList;
import java.util.List;

import utsc.apps.utschedule.R;
import utsc.apps.utschedule.classes.Assignment;
import utsc.apps.utschedule.classes.Course;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

/**
 * The list adapter for assignment fragment.
 */
public class AssignmentListAdapter extends BaseExpandableListAdapter {

	private static final String ADD_TEXT="+ Add new assignment";
	private static final String ADD_MARK="Add\nMark";
	private ArrayList<Course> _courses;
	private Context _context;
	private SparseIntArray _coursesMap;
	
	/**
	 * This constructor takes in a list of courses (without tutorials), and a context.
	 * @param courses
	 * @param context
	 */
	public AssignmentListAdapter(List<Course> courses,Context context){
		if (courses!=null) {
			_courses=new ArrayList<Course>(courses);
			//setup a helper map for courses
			_coursesMap=new SparseIntArray();
			int i=0;
			for (Course course : courses) {
				_coursesMap.put(course.get_courseID(), i);
				i++;
			}
		}
		_context=context;
	}

	@Override
	public Course getGroup(int groupPosition) {
		if (_courses!=null) {
			return _courses.get(groupPosition);
		}
		return null;
	}

	@Override
	public int getGroupCount() {
		if (_courses!=null) {
			return _courses.size();
		}
		return 0;
	}
	
	/**
	 * This method is used to refresh the underlying course list.
	 * @param _courses
	 */
	public void set_courses(ArrayList<Course> _courses) {
		this._courses = _courses;
		_coursesMap=new SparseIntArray();
		int i=0;
		for (Course course : _courses) {
			_coursesMap.put(course.get_courseID(), i);
			i++;
		}
		super.notifyDataSetChanged();
	}
	
	/**
	 * This is an overloaded version of the default <code>notifyDataSetChanged</code> method to just refresh the corresponding course.
	 * @param courseID
	 */
	public void notifyDataSetChanged(int courseID){
		int courseID1=_coursesMap.get(courseID);
		final Course c=_courses.get(courseID1);
			c.refreshAssignmentList();
			super.notifyDataSetChanged();
	}
	
	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		ViewHolder holder;
		//first inflate our view and cache the ui elements into its viewholder object
		if (convertView==null) {
			convertView=LayoutInflater.from(_context).inflate(R.layout.course_list_item, null);
			holder=new ViewHolder();
			holder._txtCourse=(TextView) convertView.findViewById(R.id.txt_list_course);
			holder._colorCourse=(TextView) convertView.findViewById(R.id.color_cell_course);
			holder._txtCountAssignments=(TextView) convertView.findViewById(R.id.txt_list_innerbox_content);
			convertView.setTag(holder);
		}else {
			//always retrieve the viewholder from the tag
			holder=(ViewHolder) convertView.getTag();
		}
		Course c=getGroup(groupPosition);
		holder._txtCourse.setText(c.toString());
		Drawable colorDrawable=holder._colorCourse.getBackground();
		holder._txtCountAssignments.setText(Integer.toString(c.get_assignmentsDueCount()));
		if (colorDrawable instanceof LayerDrawable) {
			((LayerDrawable) colorDrawable).getDrawable(0).setColorFilter(c.get_color(), PorterDuff.Mode.SRC_ATOP);
		}
		return convertView;
	}

	@Override
	public boolean isEmpty() {
		if (_courses!=null) {
			return _courses.isEmpty();
		}
		return false;
	}

	/**
	 * A viewholder for parent row items.
	 */
	private static class ViewHolder{
		TextView _txtCourse;
		TextView _colorCourse;
		TextView _txtCountAssignments;
	}
	
	/**
	 * A viewholder for assignment row items.
	 */
	private static class AssignmentViewHolder{
		TextView _txtAssignmentName;
		TextView _txtDueTime;
		TextView _txtStatus;
		TextView _txtGrade;
	}

	/**
	 * Return the corresponding assignment child from parent course. 
	 */
	@Override
	public Assignment getChild(int groupPosition, int childPosition) {
		final Course c=_courses.get(groupPosition);
		final ArrayList<Assignment> assignmentsList=c.get_assignmentList();
		if (!assignmentsList.isEmpty() && assignmentsList.size()>childPosition) {
			Assignment assignment=assignmentsList.get(childPosition);
			return assignment;
		}else {
			return null;
		}
	}

	@Override
	public long getChildId(int groupPosition, int childPosition) {
		return childPosition;
	}

	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		AssignmentViewHolder holder;
		if (convertView==null) {
			convertView=LayoutInflater.from(_context).inflate(R.layout.assignment_list_item, null);
			holder=new AssignmentViewHolder();
			holder._txtAssignmentName=(TextView) convertView.findViewById(R.id.txt_assignment_title);
			holder._txtDueTime=(TextView) convertView.findViewById(R.id.txt_assignment_duetime);
			holder._txtStatus=(TextView)convertView.findViewById(R.id.txt_status);
			holder._txtGrade=(TextView) convertView.findViewById(R.id.txt_grade);
			convertView.setTag(holder);
		}else {
			holder=(AssignmentViewHolder) convertView.getTag();
		}
		Assignment a=getChild(groupPosition, childPosition);
		//since we always append an extra item for adding new assignment,
		//so we might get a null child
		if (a!=null) {
			holder._txtAssignmentName.setPadding(0, 0, 0, 0);
			//we only show the "done" status when it is expired 
			if (a.is_expired()) {
				holder._txtAssignmentName.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG);
				holder._txtStatus.setVisibility(View.VISIBLE);
			}else {
				holder._txtAssignmentName.setPaintFlags(Paint.ANTI_ALIAS_FLAG);
				holder._txtStatus.setVisibility(View.INVISIBLE);
			}
			holder._txtAssignmentName.setText(a.get_Title());
			holder._txtDueTime.setVisibility(View.VISIBLE);
			holder._txtDueTime.setText(a.get_DueDate()+" "+a.get_DueTime());
			
			//we also only show the mark after expired
			if (a.is_expired()) {
				holder._txtGrade.setVisibility(View.VISIBLE);
				//however, we only show the mark if there is a mark already setup
				if (a.get_mark()>0 && a.get_total()>0) {
					holder._txtGrade.setText(a.get_grade().toShortString());
				}else {
					holder._txtGrade.setText(ADD_MARK);
				}
			}else {
				holder._txtGrade.setVisibility(View.INVISIBLE);
			}
		}else {
			//we are here because this position is for the add button
			//simply remove all the unnecessary views and adjust the paddings 
			holder._txtAssignmentName.setPadding(0, 20, 0, 20);
			holder._txtAssignmentName.setPaintFlags(Paint.ANTI_ALIAS_FLAG);
			holder._txtAssignmentName.setText(ADD_TEXT);
			holder._txtDueTime.setVisibility(View.GONE);
			holder._txtStatus.setVisibility(View.INVISIBLE);
			holder._txtGrade.setVisibility(View.INVISIBLE);
		}
		
		return convertView;
	}


	/**
	 * Get the children count, this will always return n+1 because we always append a dummy child at the end for add button.
	 */
	@Override
	public int getChildrenCount(int groupPosition) {
		int count=_courses.get(groupPosition).get_assignmentList().size();
		if (count>0) {
			return count+1;
		}
		return 1;
	}

	@Override
	public long getGroupId(int groupPosition) {
		return groupPosition;
	}

	@Override
	public boolean hasStableIds() {
		return false;
	}

	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		return true;
	}
}
